///*
// * jpeg_mem.cpp
// *
// *  Created on: 2016年1月19日
// *      Author: guyadong
// */
//#include <algorithm>
//#include <type_traits>
//#include <iostream>
//#include <vector>
//#include <cstring>
//#include "assert_macros.h"
//#include "jpeg_mem_advance.h"
//#include "raii.h"
//jpeg_custom_output_fun jpeg_custom_output_default=[](j_common_ptr){};
///* 自定义jpeg图像压缩/解压缩过程中错误退出函数 */
//METHODDEF(void) jpeg_mem_error_exit (j_common_ptr cinfo) {
//	// 调用 format_message 生成错误信息
//	char err_msg[JMSG_LENGTH_MAX];
//	(*cinfo->err->format_message) (cinfo,err_msg);
//	// 抛出c++异常
//	throw jpeg_mem_exception(err_msg);
//}
///* 将图像数据输出为jpeg格式的内存数据块,调用传入的finishe_output回调函数来处理压缩后的内存图像数据
// * 图像信息及获取图像行数据的方式都由compress_instance定义
// * custom用于设置图像输出参数
// * 出错抛出 jpeg_mem_exception
// */
//void save_jpeg_mem(jpeg_compress_interface& compress_instance,
//									const mem_finish_output_fun& finish_output,
//									const unsigned int quality
//									){
//	// 输出图像数据缓冲区
//	unsigned char* outBuffer = nullptr;
//	// 输出图像数据缓冲区长度(压缩后的图像大小)
//	unsigned long bufferSize = 0;
//	bool jpeg_compress_finished=false;
//	// 定义一个压缩对象
//	jpeg_compress_struct cinfo;
//	//用于错误信息
//	jpeg_error_mgr jerr;
//	// 错误输出绑定到压缩对象
//	cinfo.err = jpeg_std_error(&jerr);
//	// 设置自定义的错误处理函数
//	jerr.error_exit = jpeg_mem_error_exit;
//	// RAII对象在函数结束时释放资源
//	gdface::raii buffer_guard([&](){
//		jpeg_finish_compress(&cinfo);
//		jpeg_destroy_compress(&cinfo);
//		// 压缩正常结束则调用finish_output
//		if(jpeg_compress_finished)
//			finish_output(outBuffer, bufferSize);
//		if (nullptr != outBuffer)
//			free(outBuffer);
//	});
//	// 初始化压缩对象
//	jpeg_create_compress(&cinfo);
//	jpeg_mem_dest(&cinfo, &outBuffer, &bufferSize); // 设置内存输出缓冲区
//	compress_instance.start_output(cinfo);
//	jpeg_set_defaults(&cinfo);
//	jpeg_set_quality(&cinfo, quality<100?quality:100, true);
//	compress_instance.custom_output((j_common_ptr)(&cinfo)); // 执行自定义参数设置函数
//	jpeg_start_compress(&cinfo, true);
//	while (cinfo.next_scanline < cinfo.image_height) {
//		compress_instance.get_pixel_rows(cinfo.next_scanline);
//		jpeg_write_scanlines(&cinfo, compress_instance.buffer.data(), (JDIMENSION)compress_instance.buffer.size());
//	}
//	jpeg_compress_finished=true;
//}
//
//void save_jpeg_mem(const fs_image_matrix &matrix,
//									const mem_finish_output_fun& finish_output,
//									const unsigned int quality,
//									const jpeg_custom_output_fun &custom
//									){
//	jpeg_compress_default default_compress_instance(matrix);
//	default_compress_instance.custom_output= custom;
//	save_jpeg_mem(default_compress_instance,	finish_output);
//}
//std::string jwp_save_jpeg_mem_as_string(const fs_image_matrix & matrix, const unsigned int quality) {
//	std::string out;
//	save_jpeg_mem(matrix,
//		[&](const uint8_t *img, size_t size) {
//		out = std::string((char*)img, size);
//	}, quality);
//	return out;
//}
//std::vector<uint8_t> jwp_save_jpeg_mem_as_vector(const fs_image_matrix & matrix, const unsigned int quality) {
//	std::vector<uint8_t> out;
//	save_jpeg_mem(matrix,
//		[&](const uint8_t *img, size_t size) {
//		out = std::vector<uint8_t>(img, img + size);
//	}, quality);
//	return out;
//}
//void save_jpeg_gray_mem(const fs_image_matrix &matrix,
//									const mem_finish_output_fun& finish_output,
//									const unsigned int quality
//									){
//	static auto custom_output_gray=[](j_common_ptr cinfo) {
//			jpeg_set_colorspace((j_compress_ptr)cinfo, JCS_GRAYSCALE);
//		};
//	save_jpeg_mem(matrix,finish_output,quality,custom_output_gray);
//}
//std::string jwp_save_jpeg_gray_mem_as_string(const fs_image_matrix & matrix, const unsigned int quality) {
//	std::string out;
//	save_jpeg_gray_mem(matrix,
//		[&](const uint8_t *img, size_t size) {
//		out = std::string((char*)img, size);
//	}, quality);
//	return out;
//}
//std::vector<uint8_t> jwp_save_jpeg_gray_mem_as_vector(const fs_image_matrix & matrix, const unsigned int quality) {
//	std::vector<uint8_t> out;
//	save_jpeg_gray_mem(matrix,
//		[&](const uint8_t *img, size_t size) {
//		out = std::vector<uint8_t>(img, img + size);
//	}, quality);
//	return out;
//}
///* 将jpeg格式的内存数据块jpeg_data解压缩 
// * 图像行数据存储的方式都由decompress_instance定义
// * 如果数据为空或读取数据出错抛出 jpeg_mem_exception
// */
//void load_jpeg_mem(const uint8_t *jpeg_data,size_t size,
//		 jpeg_decompress_interface &decompress_instance) {
//	if(nullptr==jpeg_data||0==size)
//		throw jpeg_mem_exception("empty image data");
//	// 定义一个压缩对象 
//	jpeg_decompress_struct  dinfo;
//	//用于错误信息 
//	jpeg_error_mgr jerr;
//	// 错误输出绑定到压缩对象 
//	dinfo.err = jpeg_std_error(&jerr);
//	// 设置自定义的错误处理函数 
//	jerr.error_exit = jpeg_mem_error_exit;
//	// RAII对象在函数结束时释放资源
//	gdface::raii buffer_guard([&](){
//		jpeg_finish_decompress(&dinfo);
//		jpeg_destroy_decompress(&dinfo);
//	});
//	// 初始化压缩对象
//	jpeg_create_decompress(&dinfo);
//	jpeg_mem_src(&dinfo, (uint8_t*)jpeg_data, (unsigned long)size); // 设置内存输出缓冲区
//	(void) jpeg_read_header(&dinfo, true);
//	decompress_instance.custom_output((j_common_ptr)&dinfo); // 执行自定义参数设置函数
//	(void) jpeg_start_decompress(&dinfo);
//	// 输出通道数必须是1/3/4
//	if (dinfo.output_components != 1 && dinfo.output_components != 3 && dinfo.output_components != 4) {
//		throw jpeg_mem_exception(
//			"load_jpeg_mem(): Failed to load JPEG data cause by output_components error");
//	}
//	decompress_instance.start_output(dinfo);
//	JDIMENSION num_scanlines;
//	JDIMENSION expectd_lines;
//	while (dinfo.output_scanline  < dinfo.output_height) {
//		num_scanlines = jpeg_read_scanlines(&dinfo, decompress_instance.buffer.data(),
//				(JDIMENSION)decompress_instance.buffer.size());
//		expectd_lines=std::min((dinfo.output_height-dinfo.output_scanline),(JDIMENSION)decompress_instance.buffer.size());
//		// 如果取到的行数小于预期的行数，则图像数据不完整抛出异常
//		if (num_scanlines<expectd_lines)
//			throw jpeg_mem_exception("load_jpeg_mem(): Incomplete data");
//		decompress_instance.put_pixel_rows(num_scanlines);
//	}
//}
//
//fs_image_matrix load_jpeg_mem(const uint8_t *jpeg_data,size_t size,	const jpeg_custom_output_fun &custom) {
//	jpeg_decompress_default default_decompress_instance;
//	default_decompress_instance.custom_output = custom;
//	load_jpeg_mem(jpeg_data,size,default_decompress_instance);
//	return std::move(default_decompress_instance.matrix);
//}
//
//fs_image_matrix jwp_load_jpeg_mem(const void * jpeg_data, size_t size)
//{
//	return load_jpeg_mem((uint8_t *)jpeg_data, size);
//}
//
//fs_image_matrix jwp_load_jpeg_gray_mem(const void *jpeg_data,size_t size) {
//	static auto custom_output_gray=[](j_common_ptr dinfo) {
//			((j_decompress_ptr)dinfo)->out_color_space = JCS_GRAYSCALE;
//		};
//	return load_jpeg_mem((uint8_t *)jpeg_data,size,custom_output_gray);
//}
///* 图像数据(输出/输入)接口 */
//struct jpeg_io_interface{
//	// 虚函数用于初始化图像数据源或目标
//	virtual void open(j_common_ptr info)const=0;
//	// 虚函数用于关闭数据IO
//	virtual void close()const =0;
//	virtual ~jpeg_io_interface()=default;
//};
//template<bool COMPRESS>
//struct jpeg_io_mem:public jpeg_io_interface{
//	mutable uint8_t *jpeg_data=nullptr;
//	mutable unsigned long size=0;
//	template<bool C=COMPRESS,typename Enable=typename std::enable_if<!C>::type>
//	jpeg_io_mem(const uint8_t *jpeg_data,size_t size):jpeg_data(const_cast<uint8_t *>(jpeg_data)),size((unsigned long)size){}
//	template<bool C=COMPRESS,typename Enable=typename std::enable_if<!C>::type>
//	jpeg_io_mem(const std::vector<uint8_t> &jpeg_data):jpeg_data(const_cast<uint8_t *>(jpeg_data.data())),size((unsigned long)jpeg_data.size()){}
//	virtual void open(j_common_ptr info)const {
//		if (COMPRESS)
//			jpeg_mem_dest((j_compress_ptr)info,&jpeg_data,&size);
//		else {
//			if (nullptr == jpeg_data || 0 == size)
//				throw jpeg_mem_exception("empty image data");
//			jpeg_mem_src((j_decompress_ptr)info, jpeg_data, size);
//		}
//	}
//	virtual void close()const{}
//};
//template<bool COMPRESS>
//struct jpeg_io_file:public jpeg_io_interface{
//	jpeg_io_file( const char *const filename):jpeg_io_file(nullptr,filename){}
//	jpeg_io_file(std::FILE *const file):jpeg_io_file(file,nullptr){}
//	virtual void open(j_common_ptr info)const {
//		if(COMPRESS)
//			jpeg_stdio_dest((j_compress_ptr)info, file);
//		else
//			jpeg_stdio_src((j_decompress_ptr)info, file);
//	}
//	virtual void close()const{
//		if(nullptr!=filename){
//			fclose(file);
//		}
//	}
//private:
//	const char *const filename;
//	mutable std::FILE * file;
//	jpeg_io_file( std::FILE *const file,const char *const filename):file(file),filename(filename){
//				if((nullptr==filename||0==strlen(filename))&&nullptr==file)
//					throw std::invalid_argument("the argument filename and file must not all be nullptr (empty)");
//				if(nullptr==this->file){
//					if(nullptr==filename||0==strlen(filename))
//						throw std::invalid_argument("the argument filename and file must not all be nullptr (empty)");
//					if(nullptr==(this->file=fopen(filename,COMPRESS?"wb":"rb"))){
//						throw std::invalid_argument(std::string("can't open file ").append(filename));
//					}
//				}
//			}
//};
///* (不解压缩)读取jpeg格式的内存数据块的基本信息返回image_matrix_pram对象
// * 如果数据为空或读取数据出错抛出 jpeg_mem_exception
// */
//fs_image_matrix read_jpeg_header(const jpeg_io_interface &src) {
//	// 定义一个压缩对象
//	jpeg_decompress_struct  dinfo;
//	// 用于错误信息
//	jpeg_error_mgr jerr;
//	// 错误输出绑定到压缩对象
//	dinfo.err = jpeg_std_error(&jerr);
//	// 设置自定义的错误处理函数
//	jerr.error_exit = jpeg_mem_error_exit;
//	// RAII对象在函数结束时释放资源
//	gdface::raii buffer_guard([&](){
//		src.close();
//		jpeg_destroy_decompress(&dinfo);
//	});
//	// 初始化压缩对象
//	jpeg_create_decompress(&dinfo);
//	src.open((j_common_ptr)&dinfo);
//	auto retcode = jpeg_read_header(&dinfo, true);
//	throw_except_if_msg(jpeg_mem_exception, JPEG_HEADER_OK != retcode, "invalid jpeg header")
//	fs_image_matrix matrix;
//	// 填充图像基本信息结构
//	matrix.width=dinfo.image_width;
//	matrix.height=dinfo.image_height;
//	matrix.color_space=(FS_COLOR_SPACE)dinfo.jpeg_color_space;
//	matrix.channels=dinfo.num_components;
//	//std::cout<<matrix.width<<"x"<<matrix.height<<"x"<<(uint32_t)matrix.channels<<" color="<<matrix.color_space<<std::endl;
//	return std::move(matrix);
//}
//fs_image_matrix jwp_read_jpeg_header_file(const char *const filename) {
//	return read_jpeg_header(jpeg_io_file<false>(filename));
//}
//fs_image_matrix jwp_read_jpeg_header_file(std::FILE *const file) {
//	return read_jpeg_header(jpeg_io_file<false>(file));
//}
//fs_image_matrix jwp_read_jpeg_header_mem(const void *jpeg_data,size_t size) {
//	return read_jpeg_header(jpeg_io_mem<false>((uint8_t*)jpeg_data,size));
//}
//
//jpeg_compress_default::jpeg_compress_default(const fs_image_matrix & matrix) :matrix(matrix), next_line(0) {
//	row_stride = matrix.get_row_stride();
//}
//
//void jpeg_compress_default::start_output(jpeg_compress_struct & cinfo) {
//	cinfo.image_width = matrix.width;
//	cinfo.image_height = matrix.height;
//	cinfo.input_components = matrix.channels;
//	cinfo.in_color_space = (J_COLOR_SPACE)matrix.color_space;
//	// buffer只保存一行像素的源数据指针
//	buffer = std::vector<JSAMPROW>(1);
//	next_line = 0;
//}
//
//void jpeg_compress_default::get_pixel_rows(JDIMENSION num_scanlines) {
//	// buffer指向当前行像素数据的地址
//	buffer[0] = const_cast<JSAMPROW>(matrix.pixels) + (next_line++)*row_stride*matrix.channels;
//}
//
//jpeg_decompress_default::jpeg_decompress_default(uint8_t align) :next_line(0), row_stride(0) {
//	matrix.align = align;
//}
//
//jpeg_decompress_default::jpeg_decompress_default() : jpeg_decompress_default(0) {}
//
//void jpeg_decompress_default::start_output(const jpeg_decompress_struct & dinfo) {
//	// 填充图像基本信息结构
//	auto b = fs_make_matrix(&matrix,
//		dinfo.output_width,
//		dinfo.output_height,
//		dinfo.output_components,
//		(FS_COLOR_SPACE)dinfo.out_color_space,
//		0,
//		nullptr);
//	if (!b) {
//		throw jpeg_mem_exception("fail to fs_make_matrix");
//	}
//	row_stride = matrix.get_row_stride();
//
//	// buffer只保存一行像素的目标数据指针
//	buffer = std::vector<JSAMPROW>(1);
//	next_line = 0;
//	// 初始化buffer指向第一像素存储地址
//	buffer[next_line] = matrix.pixels;
//}
//
//void jpeg_decompress_default::put_pixel_rows(JDIMENSION num_scanlines) {
//	// buffer指向下一行要像素存储地址
//	buffer[0] = matrix.pixels + (++next_line)*row_stride*matrix.channels;
//}
